package com.ssc.chain.tcfp.core.client;



import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * @author mingjian
 * @version 1.0
 * Create by 2025/7/10 17:48
 */
public class TusUploadService {
    private final UploadStore uploadStore;
    private final DistributedLock distributedLock;
    private final TcfpUploadProgressListener progressListener;

    public TusUploadService(UploadStore uploadStore,
                            DistributedLock distributedLock,
                            TcfpUploadProgressListener progressListener) {
        this.uploadStore = uploadStore;
        this.distributedLock = distributedLock;
        this.progressListener = progressListener;
    }

    /**
     * 创建上传资源，处理 POST /files 请求
     */
    public ResponseEntity<Void> createUpload(HttpServletRequest request) throws IOException {
        String uploadLengthStr = request.getHeader("Upload-Length");
        if (StringUtils.isBlank(uploadLengthStr)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        long uploadLength;
        try {
            uploadLength = Long.parseLong(uploadLengthStr);
            if (uploadLength < 0) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }
        } catch (NumberFormatException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        // 生成唯一上传ID
        String uploadId = UUID.randomUUID().toString();

        // 调用存储接口创建上传文件
        try {
            uploadStore.createUpload(uploadId, uploadLength);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }

        // 通知监听器开始上传
        progressListener.onStart(uploadId, uploadLength);

        // 返回 201 Created 和 Location 头部
        return ResponseEntity.status(HttpStatus.CREATED)
                .header(HttpHeaders.LOCATION, request.getRequestURL().append("/").append(uploadId).toString())
                .build();
    }

    /**
     * 查询上传进度，处理 HEAD /files/{uploadId} 请求
     */
    public ResponseEntity<Void> getUploadOffset(String uploadId) throws IOException {
        if (StringUtils.isBlank(uploadId)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        long offset;
        try {
            offset = uploadStore.getOffset(uploadId);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }

        return ResponseEntity.status(HttpStatus.OK)
                .header("Upload-Offset", String.valueOf(offset))
                .build();
    }

    /**
     * 追加上传数据，处理 PATCH /files/{uploadId} 请求
     */
    public ResponseEntity<Void> patchUpload(String uploadId, HttpServletRequest request) throws IOException {
        if (StringUtils.isBlank(uploadId)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        // 获取请求体长度
        int contentLength = request.getContentLength();
        if (contentLength <= 0) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        // 获取请求头 Upload-Offset
        String uploadOffsetHeader = request.getHeader("Upload-Offset");
        if (StringUtils.isBlank(uploadOffsetHeader)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        long requestOffset;
        try {
            requestOffset = Long.parseLong(uploadOffsetHeader);
            if (requestOffset < 0) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }
        } catch (NumberFormatException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        // 分布式锁防止并发写
        boolean lockAcquired = distributedLock.tryLock(uploadId, 5000);
        if (!lockAcquired) {
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
        }

        try {
            // 获取当前偏移量
            long currentOffset = uploadStore.getOffset(uploadId);
            if (requestOffset != currentOffset) {
                // 请求偏移与服务端偏移不符，拒绝请求
                return ResponseEntity.status(HttpStatus.CONFLICT)
                        .header("Upload-Offset", String.valueOf(currentOffset))
                        .build();
            }

            // 读取上传数据流
            try (InputStream in = request.getInputStream()) {
                // 追加数据
                uploadStore.append(uploadId, currentOffset, in, contentLength);

                long newOffset = currentOffset + contentLength;

                // 触发进度监听
                progressListener.onProgress(uploadId, newOffset, -1);

                // 判断是否完成
                // 这里假设uploadStore可查询文件大小以判断是否完成
                long uploadLength = -1;
                try {
                    uploadLength = uploadStore.getUploadLength(uploadId);
                } catch (NoSuchMethodError nsme) {
                    // 如果实现没有该方法，可忽略
                }

                if (uploadLength > 0 && newOffset >= uploadLength) {
                    uploadStore.complete(uploadId);
                    progressListener.onComplete(uploadId);
                }

                // 返回 204 No Content 和最新偏移
                return ResponseEntity.status(HttpStatus.NO_CONTENT)
                        .header("Upload-Offset", String.valueOf(newOffset))
                        .build();
            }
        } catch (Exception e) {
            progressListener.onError(uploadId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        } finally {
            distributedLock.unlock(uploadId);
        }
    }
}
